Modern programming languages such as C and C++ do not use metadata. Crucial metadata such as bounds for pointers (e.g., bounds refer to the beginning and ending addresses, i.e., lower and upper bound respectively, of the objects pointed to by a pointer) and data types for objects are not available during the execution of these programming languages, such as C/C++ programs. The lack of such metadata for a running software program often results in incorrect behavior of the program and leads to vulnerabilities. One conventional approach to add metadata is to store it adjacent to the data itself in memory, so that software or hardware can locate it; however, this requires a change in memory layout/Application Binary Interface (ABI). As a result, metadata is only used in a very specialized environment where the complete software is required to be recompiled to adhere to the new modified conventions.
Alternately, software stores the data and metadata in non-adjacent memory locations and further implements a map function to match the data with the corresponding metadata. In this case, the data is loaded into registers, while the corresponding metadata is loaded into other existing registers. Further, the software is required to keep track of the association between the data and the metadata in existing registers and perform the necessary propagation and invalidation of the metadata to keep it in sync with its corresponding data. In this case, when data is passed to functions in register parameters, the corresponding metadata also needs to be passed in registers. This results in lack of transparency and necessitates an extension to the calling convention used. Also, the implementation of this technique is inherently slow because of a high overhead it places on the software and the system, such as added register pressure, additional instructions that are needed for metadata propagation and invalidation, etc., to the point that the technique is not used in practice.
FIG. 1 illustrates a simplistic view of a processor 100 having default registers 102. A processor, such as a general purpose processor or a special purpose processor, is a semiconductor chip having electronic circuitry designed to process program code instructions. Most processors typically include a number of common architectural features, such as default registers 102. A typical register provides a small amount of storage space on the processor so certain data can be accessed using the register as opposed to accessing memory which could be a slow process; for example, a register can be used to store instruction input operands and instruction output results.
Other common architectural features may include a cache to locally store instructions and/or data, fetch circuitry to fetch instructions from cache and/or memory, write-back circuitry to store instruction results into cache and/or memory. Further, the processor 100 having registers 102 is shown to be in communication with Random-Access Memory (RAM) 104 and Read-Only Memory (ROM) 106.